package TCP.Demo3;

// FileUploadServer.java

import java.io.*;

import java.net.*;


/**

 * 文件上传服务器

 * 基于TCP协议实现文件接收功能

 */

public class FileUploadServer {

    // 服务器监听端口

    private static final int PORT = 61012;

    // 文件保存目录

    private static final String SAVE_DIR = "uploads/";


    public static void main(String[] args) {

        // 创建保存文件的目录（如果不存在）

        File saveDir = new File(SAVE_DIR);

        if (!saveDir.exists()) {

            saveDir.mkdirs();

        }



        try (ServerSocket serverSocket = new ServerSocket(PORT)) {

            System.out.println("文件上传服务器已启动，监听端口: " + PORT);



            // 持续监听客户端连接

            while (true) {

                // 接受客户端连接（阻塞方法，直到有客户端连接）

                Socket clientSocket = serverSocket.accept();

                System.out.println("客户端已连接: " + clientSocket.getInetAddress());



                // 为每个客户端创建单独的线程处理文件上传

                new Thread(new ClientHandler(clientSocket)).start();

            }

        } catch (IOException e) {

            // 处理服务器启动或客户端连接异常

            e.printStackTrace();

        }

    }


    /**

     * 客户端处理器，实现Runnable接口

     */

    private static class ClientHandler implements Runnable {

        private final Socket clientSocket;



        public ClientHandler(Socket socket) {

            this.clientSocket = socket;

        }


        @Override

        public void run() {

            try (DataInputStream dis = new DataInputStream(clientSocket.getInputStream())) {

                // 读取文件名（UTF-8编码字符串）

                String fileName = dis.readUTF();

                // 读取文件大小（长整型）

                long fileSize = dis.readLong();


                System.out.println("准备接收文件: " + fileName + "，大小: " + fileSize + " 字节");


                // 创建文件输出流，用于将接收到的数据写入文件

                FileOutputStream fos = new FileOutputStream(SAVE_DIR + fileName);

                // 创建缓冲区，用于批量读取数据

                byte[] buffer = new byte[4096];

                int bytesRead;          // 每次读取的字节数

                long totalBytesRead = 0; // 已读取的总字节数

                long lastProgressUpdate = System.currentTimeMillis(); // 上次更新进度的时间


                // 循环读取文件数据，直到完成

                while (totalBytesRead < fileSize) {

                    // 计算本次最多读取的字节数（避免读取超过文件大小的数据）

                    bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, fileSize - totalBytesRead));

                    if (bytesRead == -1) break; // 流结束标志


                    // 将读取的数据写入文件

                    fos.write(buffer, 0, bytesRead);

                    totalBytesRead += bytesRead;


                    // 每秒钟更新一次进度显示

                    long currentTime = System.currentTimeMillis();

                    if (currentTime - lastProgressUpdate > 1000) {

                        double progress = (double) totalBytesRead / fileSize * 100;

                        System.out.printf("已接收: %.2f%%\n", progress);

                        lastProgressUpdate = currentTime;

                    }

                }


                // 关闭文件输出流

                fos.close();

                System.out.println("文件 " + fileName + " 接收完成，大小: " + totalBytesRead + " 字节");


            } catch (IOException e) {

                // 处理文件传输过程中的异常

                e.printStackTrace();

            } finally {

                try {

                    // 关闭客户端连接

                    clientSocket.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

    }

}
